package com.gitee.loyo.interfaces

import com.gitee.loyo.Helper
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import kotlin.reflect.KClass

interface LazyReadMapper {
    fun <T : Any> `as`(kType: KClass<T>): T?
    fun <T : Any> `as`(typeRef: TypeReference<T>): T?
    fun <T : Any> asList(kType: KClass<T>): List<T>
    fun <T : Any> asList(typeRef: TypeReference<T>): List<T>
}


abstract class TypeReference<T>(private var type: Type? = null){
    fun isParameterizedPair() = getType().let { type ->
        type is ParameterizedType && type.rawType == Pair::class.java
    }

    fun getPairTypes(): Pair<KClass<*>, KClass<*>>{
        val type = getType()
        return (type as ParameterizedType).actualTypeArguments.let { args ->
            (Helper.typeToClass(args[0], 0).kotlin) to (Helper.typeToClass(args[1], 0).kotlin)
        }
    }

    fun isParameterizedTriple() = getType().let { type ->
        type is ParameterizedType && type.rawType == Triple::class.java
    }

    fun getTripleTypes(): Triple<KClass<*>, KClass<*>, KClass<*>>{
        val type = getType()
        return (type as ParameterizedType).actualTypeArguments.let { args ->
            Triple(Helper.typeToClass(args[0], 0).kotlin, Helper.typeToClass(args[1], 0).kotlin, com.gitee.loyo.Helper.typeToClass(args[2], 0).kotlin)
        }
    }

    fun listType(): KClass<*>{
        val type = getType()
        return Helper.typeToClass((type as ParameterizedType).actualTypeArguments[0], 0).kotlin
    }

    fun kotlinType():KClass<*>{
        val type = getType()
        return Helper.typeToClass(type, 0).kotlin
    }

    fun getType(): Type {
        if(type == null){
            type = (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0]
        }
        return type!!
    }
}